package com.xl.utils.util.fanxing;

import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author xionglin
 * @Classname FanxingDemo
 * @Description 泛型测试
 * @Date 2021/4/25 11:07
 */
public class FanxingDemo {
    /**
     * 泛型的讲解：https://www.cnblogs.com/coprince/p/8603492.html
     */

    public static void main(String[] args) {
        //测试1
        //test1();
        //test2();
        test3();

    }

    public static void test1() {
        List arrayList = new ArrayList();
        arrayList.add("aaaa");
        arrayList.add(100);

        for (int i = 0; i < arrayList.size(); i++) {
            String item = (String) arrayList.get(i);
            System.out.println("泛型测试item = " + item);
        }
        //毫无疑问，程序的运行结果会以崩溃结束：
        //java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String}
    }
    public static void test2() {
        //特性 ，泛型只在编译阶段有效。看下面的代码：
        List<String> stringArrayList = new ArrayList<>();
        List<Integer> integerArrayList = new ArrayList<>();

        Class classStringArrayList = stringArrayList.getClass();
        Class classIntegerArrayList = integerArrayList.getClass();

        if(classStringArrayList.equals(classIntegerArrayList)){
            System.out.println(("泛型测试类型相同"));
        }
        /**
         * 通过上面的例子可以证明，在编译之后程序会采取去泛型化的措施。
         * 也就是说Java中的泛型，只在编译阶段有效。在编译过程中，正确检验泛型结果后，
         * 会将泛型的相关信息擦出，并且在对象进入和离开方法的边界处添加类型检查和类型转换的方法。
         * 也就是说，泛型信息不会进入到运行时阶段。
         * 对此总结成一句话：泛型类型在逻辑上看以看成是多个不同的类型，实际上都是相同的基本类型。
         */
    }
    /**
     * ------------------>类型擦除<----------------
     * 我们现在可以下结论了，在泛型类被类型擦除的时候，之前泛型类中的类型参数部分如果没有指定上限，
     * 如 <T>则会被转译成普通的 Object 类型，如果指定了上限如 <T extends String>则类型参数就被替换成类型上限。
     */
    public static void test3(){
        List<Integer> ls = new ArrayList<>();
        ls.add(23);
//		ls.add("text");直接add字符串编译不能通过，利用反射可以绕开，原因就是类型擦除，List类型擦除之后其实元素的类型就是object
        try {
            Method method = ls.getClass().getDeclaredMethod("add",Object.class);

            //在定义的Integer的List中放入字符串
            method.invoke(ls,"test");
            //在定义的Integer的List中放入double
            method.invoke(ls,42.9f);
        } catch (NoSuchMethodException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        for ( Object o: ls){
            //成功打印
            System.out.println(o);

        }

    }


}